<?php
//	Copyright (C) 2010  Thomas Andersen (thomas.1.andersen@gmail.com)
//	
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//	
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//	
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.	
	
//Set the content-type header to xml
header("Content-type: text/xml");

  include "functions/db.php";
  include "functions/misc.php";
  include "functions/encrypt.php";

$operation = "none";
$params = array();
$paramidx = NULL;
$opensecrets = new opensecretsclass();

function startElement($parser, $name, $attrs) 
{
    global $operation, $paramidx;
    $paramidx = NULL;
    switch($name)
    {
    case 'SERVICECALL':
        $operation = $attrs['OPERATION'];
        break;
    case 'PARAM':
        $paramidx = $attrs['ID'];
        break;
    }
}

function endElement($parser, $name) 
{
    global $operation, $opensecrets, $params;

    switch($name)
    {
    case 'SERVICECALL':
        switch($operation)
        {
        case 'Challenge':
            $opensecrets->Challenge($params);
            break;
        case 'Login':
            $opensecrets->Login($params);
            break;
        case 'Logout':
            $opensecrets->Logout($params);
            break;
        case 'GetUserInfo':
            $opensecrets->GetUserInfo($params);
            break;
        case 'CreateUser':
            $opensecrets->CreateUser($params);
            break;
        case 'CheckSession':
            $opensecrets->CheckSession($params);
            break;
        case 'CreateSafe':
            $opensecrets->CreateSafe($params);
            break;
		case 'DeleteSafe':
			$opensecrets->DeleteSafe($params);
			break;
		case 'SafeSearch':
			$opensecrets->SafeSearch($params);
			break;
		default:
            $opensecrets->Error('Unknown operation');
            break;
        }
        break;
    }
}

function characterData($parser, $data) 
{
    global $params, $paramidx;
    if (!is_null($paramidx))
    {
        $params[$paramidx] = rawurldecode($data);
    }
}

// Handle xml request.
if (isset($HTTP_RAW_POST_DATA)) {
    $request = $HTTP_RAW_POST_DATA;
} else {
    $request = file_get_contents('php://input');
}

$xml_parser = xml_parser_create();

// use case-folding so we are sure to find the tag in $map_array
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");


if (!xml_parse($xml_parser, $request)) {
    $opensecrets->Error('Error in xml');
}


?>

<?php

class opensecretsclass {
    public function Response($resp)
    {
        global $operation;

        echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
        echo "<serviceresponse operation=\"" . $operation . "\">";
        echo "<items>";
        reset($resp);
        while (list($key, $val) = each($resp)) {
            echo "<field id=\"$key\">" . rawurlencode($val) . "</field>\n";
        }
        echo "</items>";
        echo "</serviceresponse>";

    }
    public function Error($reason)
    {
        global $operation;
        echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
        echo "<serviceresponse id=\"" . $operation . "\">";
        echo "<error>" . $reason . "</error>";
        echo "</serviceresponse>";
		return false;
    }


    // Create challenge key.
    public function Challenge($parm)
    {
        $result = array();
	    $link = OpenSql();

        $unique = false;
        while(!$unique)
        {
            $sessionid = CreateSessionId();
            $query = "SELECT userid FROM sessionlist WHERE sessionid = '$sessionid'";
			if (!($subresult=mysql_query($query)))
                return $this->Error("Could not select from session");
            if (($row = mysql_fetch_array($subresult)))
                $unique = false;
            else
                $unique = true;

            if ($unique)
            {
			    $query = "INSERT INTO sessionlist (sessionid,userid,sessiontime) VALUES ('$sessionid',0,NOW())";
			    if (!mysql_query($query))
                    return $this->Error("Could not insert session");
            }
        }
        $result['value'] = MD5($sessionid);
	    CloseSql($link);
        $this->CleanSessions();

        $this->Response($result);
    }

    public function Login($parm)
    {
        if (!isset($parm['sessionid']))
        {
            return $this->Error('Argument sessionid missing');
        }
        if (!isset($parm['name']))
        {
            return $this->Error('Argument name missing');
        }
        if (!isset($parm['password']))
        {
            return $this->Error('Argument password missing');
        }
        $name = strtolower($parm['name']);
        $password = $parm['password'];
        $sessionid = $parm['sessionid'];
        $result = array();
	    $link = OpenSql();

        // Lookup user.
        $userid = $this->GetSession($sessionid);
        if ($userid != 0)
        {
            return $this->Error("Internal error");
        }
        $subquery = "SELECT userid FROM userlist WHERE name = '$name' and MD5(CONCAT(password,'$sessionid')) = '$password' AND active=1";
        $subresult = mysql_query($subquery); 
        if (!$subresult)
        {
            return $this->Error("Error reading userlist");
        }
        if ($row = mysql_fetch_array($subresult))
        {
            list($userid) = $row;
			$query = "UPDATE sessionlist SET userid=$userid,sessiontime=NOW() WHERE MD5(sessionid) = '$sessionid'";
			if (!mysql_query($query))
                return $this->Error("Could not insert session");
            $result['sessionid'] = $sessionid;
			$result['known'] = 1;
        }

	    CloseSql($link);
        $this->CleanSessions();

        $this->Response($result);
    }

    public function Logout($parm)
    {
        if (!isset($parm['sessionid']))
        {
            return $this->Error('Argument sessionid missing');
        }
        $sessionid = $parm['sessionid'];
        $result = array();
	    $link = OpenSql();
        // Lookup session.
        $userid = $this->GetSession($sessionid);
        if ($userid>0)
        {
            $subquery = "DELETE FROM sessionlist WHERE userid = '$userid'";
            if (!mysql_query($subquery))
                return $this->Error("Delete of session failed.");

            if ($row = mysql_fetch_array($subresult))
            {
                $result['result'] = "OK";
            }
        }

	    CloseSql($link);
        $this->CleanSessions();
        $this->Response($result);
    }

    public function CheckSession($parm)
    {
        if (!isset($parm['sessionid']))
        {
			return $this->Error('Internal Error: Argument sessionid missing');
        }
        $sessionid = $parm['sessionid'];
        $result = array();
	    $link = OpenSql();
        // Lookup session.
        $subquery = "SELECT userid FROM sessionlist WHERE MD5(sessionid) = '$sessionid' AND sessiontime > DATE_SUB(NOW(),INTERVAL 3 HOUR)";
        $subresult = mysql_query($subquery);
        if (!$subresult)
			return $this->Error("Internal error: Read from sessionlist failed." . mysql_error());

        if ($row = mysql_fetch_array($subresult))
        {
            list($userid) = $row;
			if ($userid > 0) {
				$result['known'] = 1;
			}
           $result['sessionid'] = $sessionid;
        }

	    CloseSql($link);
        $this->CleanSessions();
        $this->Response($result);
    }

	function SessionOk($sessionid)
	{
        $subquery = "UPDATE sessionlist SET sessiontime=NOW() WHERE MD5(sessionid) = '$sessionid'";
        $subresult = mysql_query($subquery);   
        if (!$subresult)
			return $this->Error("Update of session failed. Your session has probably timed out. Press F5 to refresh view.");
		return true;
	}

    function GetSession($sessionid)
    {
        // Lookup session.
        $userid = GetUserFromSession($sessionid);
        $subquery = "UPDATE sessionlist SET sessiontime=NOW() WHERE MD5(sessionid) = '$sessionid'";
        $subresult = mysql_query($subquery);   
        if (!$subresult)
			return $this->Error("Update of session failed. Your session has probably timed out. Press F5 to refresh view.");

        return $userid;
    }

    function CleanSessions()
    {
	    $link = OpenSql();
        // Delete old sessions.
        $subquery = "DELETE FROM sessionlist WHERE sessiontime < DATE_SUB(NOW(),INTERVAL 3 HOUR)";
        mysql_query($subquery);

	    CloseSql($link);
    }

    public function GetUserInfo($parm)
    {
        if (!isset($parm['sessionid']))
        {
			return $this->Error('Internal error: Argument sessionid missing');
        }
        $sessionid = $parm['sessionid'];
        $result = array();
	    $link = OpenSql();

		if (!$this->SessionOk($sessionid))
			return;

	    $userid = GetUserFromSession($sessionid);

		$result['id'] = $userid;
		if ($userid > 0) {
			$subquery = "SELECT name,first,last,addr1,addr2,city,postcode,country,email FROM userlist WHERE closed = 0 AND userid=$userid";
			$subresult = mysql_query($subquery);
			if (!$subresult)
				return $this->Error("Internal error: Read from userlist failed." . mysql_error());

			if($row = mysql_fetch_array($subresult))
			{
				list($name,$first,$last,$addr1,$addr2,$city,$postcode,$country,$email) = $row;
				$result['name'] = $name;
				$result['first'] = $first;
				$result['last'] = $last;
				$result['addr1'] = $addr1;
				$result['addr2'] = $addr2;
				$result['city'] = $city;
				$result['postcode'] = $postcode;
				$result['country'] = $country;
				$result['email'] = $email;
			}
		}

	    CloseSql($link);
        $this->Response($result);
    }
    
    public function CreateUser($parm)
    {
        if (!isset($parm['sessionid']))
        {
			return $this->Error('Internal error: Argument sessionid missing');
        }
        $sessionid = $parm['sessionid'];
        if (!isset($parm['name']))
        {
			return $this->Error('Internal error: Argument name missing');
        }
        $name = strtolower($parm['name']);

        if (!isset($parm['email']))
        {
			return $this->Error('Internal error: Argument email missing');
        }
        $email = $parm['email'];

        if (!isset($parm['password']))
        {
			return $this->Error('Internal error: Argument password missing');
        }
        $password = $parm['password'];

        if (!isset($parm['password2']))
        {
			return $this->Error('Internal error: Argument password2 missing');
        }
        $password2 = $parm['password2'];

        $result = array();
	    $link = OpenSql();

		if (!$this->SessionOk($sessionid))
			return;
			
		if (strcmp($password,$password2))
		    return $this->Error("The two passwords does not match");

	    $query = "INSERT INTO userlist (name, password, activateid, email) VALUES ('$name','$password','$sessionid', '$email')";
	    if (!mysql_query($query))
            return $this->Error("Could not insert user: " . mysql_error());

		// Send mail.
		$server = $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'];
		$pos = strrpos($server, '/');
		$server = substr($server,0,$pos);
		$contentbuf = "To activate your user on OpenSecrets go to: https://" . $server . "?activate=" . $sessionid;
		@mail($email, "Created user for OpenSecrets",addslashes($contentbuf));

	    CloseSql($link);
        $this->Response($result);
    }


    public function CreateSafe($parm)
    {
        if (!isset($parm['sessionid']))
        {
			return $this->Error('Internal error: Argument sessionid missing');
        }
        $sessionid = $parm['sessionid'];
		if (!isset($parm['key']))
		{
			return $this->Error('Internal error: Argument key missing');
		}
		$key = $parm['key'];
        if (!isset($parm['name']))
        {
			return $this->Error('Internal error: Argument name missing');
        }
        $name = $parm['name'];

		$user = "";
        if (isset($parm['user']))
        {
			$user = $parm['user'];
        }

		$password = "";
        if (isset($parm['password']))
        {
			$password = $parm['password'];
        }

        $result = array();
	    $link = OpenSql();

		if (!$this->SessionOk($sessionid))
			return;
			
	    $userid = GetUserFromSession($sessionid);
		
		//$name = Encrypt("Name" . $key , "NameField", $name);
		//$user = Encrypt("User" . $key , "UserField", $user);
		//$password = Encrypt("Pass" . $key , "PassField", $password);

	    $query = "REPLACE INTO safe (userid, name, user, password) VALUES ($userid, '$name','$user', '$password')";
	    if (!mysql_query($query))
            return $this->Error("Could not insert safe: " . mysql_error());

	    CloseSql($link);
        $this->Response($result);
    }

	public function DeleteSafe($parm)
	{
		if (!isset($parm['sessionid']))
		{
			return $this->Error('Internal error: Argument sessionid missing');
		}
		$sessionid = $parm['sessionid'];
		if (!isset($parm['key']))
		{
			return $this->Error('Internal error: Argument key missing');
		}
		$key = $parm['key'];
		if (!isset($parm['name']))
		{
			return $this->Error('Internal error: Argument name missing');
		}
		$name = $parm['name'];
		
		
		$result = array();
		$link = OpenSql();
		
		if (!$this->SessionOk($sessionid))
			return;
		
		$userid = GetUserFromSession($sessionid);
		
		//$name = Encrypt("Name" . $key , "NameField", $name);
		$query = "DELETE FROM safe WHERE userid = $userid AND name = '$name'";
		if (!mysql_query($query))
			return $this->Error("Could not delete safe: " . mysql_error());
		
		CloseSql($link);
		$this->Response($result);
	}

	public function SafeSearch($parm)
	{
		if (!isset($parm['sessionid']))
		{
			return $this->Error('Internal error: Argument sessionid missing');
		}
		$sessionid = $parm['sessionid'];
		if (!isset($parm['key']))
		{
			return $this->Error('Internal error: Argument key missing');
		}
		$key = $parm['key'];
		$searchname = null;
		if (isset($parm['name']))
		{
			$searchname = $parm['name'];
		}
		
		$result = array();
		$link = OpenSql();
		
		if (!$this->SessionOk($sessionid))
			return;
		
		$userid = GetUserFromSession($sessionid);
		
		$subquery = "SELECT name, user, password FROM safe WHERE userid=$userid";
		$subresult = mysql_query($subquery);
		if (!$subresult)
			return $this->Error("Internal error: Read from safe failed." . mysql_error());
		
		$qi = 0;
		while($row = mysql_fetch_array($subresult))
		{
			list($name,$user,$password) = $row;
			//$name = Decrypt("Name" . $key ,"NameField", $name);
			//if (!$searchname || stristr($name, $searchname)) {
				$result["name$qi"] = $name;
			$result["user$qi"] = $user;//Decrypt("User" . $key , "UserField", $user);
			$result["password$qi"] = $password;//Decrypt("Pass" . $key , "PassField", $password);
				$qi++;
			//}
		}			
		
		CloseSql($link);
		$this->Response($result);
	}
}
?>
